package com.ecarx.vhaltests.hy11.testcases.system.seatadjustment;

import static android.car.VehiclePropertyIds.SEAT_BACKREST_ANGLE_2_MOVE;

import android.car.VehicleAreaSeat;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

//  N5  [SW_FC_004_050] 3.2.19 第二排靠背调节 2ndRowSeatBackrestAdjustment--移动
public class SeatBackrestAngle2MoveTest extends VhalUnitTestBase {
    public static final String TAG = "SEAT_BACKREST_ANGLE_2_MOVE";
    private static int halValueRow2Left;
    private static int halStatusRow2Left;
    private static int halValueRow2Right;
    private static int halStatusRow2Right;
    final static Object lockRow2Left = new Object();
    final static Object lockRow2Right = new Object();

    private static final int BACKREST_ANGLE_OFF = 0;
    private static final int BACKREST_ANGLE_FORWARD = 1;
    private static final int BACKREST_ANGLE_BACKWARD = 2;
    private static final int PARAM_INVALID = 6;

    private static final IpcpClient ipcpClient = new IpcpClient();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, SEAT_BACKREST_ANGLE_2_MOVE, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig();
    }

    @Test
    public void testSeatBackrestAngle2MoveAvail() {
        setSeatBackrestAngle2MoveAvail();
        lockRow2Left();
        lockRow2Right();
        Assert.assertEquals(halStatusRow2Left, 0);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveIsAvailLeft();
        testSeatBackrestAngle2MoveIsAvailRight();
    }

    @Test
    public void testSeatBackrestAngle2MoveNotAvail() {
        setSeatBackrestAngle2MoveNotAvail();
        lockRow2Left();
        lockRow2Right();
        Assert.assertEquals(halStatusRow2Left, 1);
        Assert.assertEquals(halStatusRow2Right, 1);
        testSeatBackrestAngle2MoveNotAvailLeft();
        testSeatBackrestAngle2MoveNotAvailRight();
    }

    @Test
    public void testSeatBackrestAngle2MoveBtnPress() {// 硬按键按下，无论是前还是是后需要变为idle
        setSeatBackrestAngle2MoveAvail();
        setCDM(100, 1, 1, 100, 1, 1);// 硬按键按下
        lockRow2Left();
        lockRow2Right();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 1);
        Assert.assertEquals(halStatusRow2Right, 1);
    }


    @Test
    public void testSeatBackrestAngle2MoveRow2LeftForward() {// 正常向前,移动中
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_FORWARD);
        setCDMDriver(100, 0, 1);// 当前实时角度100，硬按键未按下，靠背正在向前调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_FORWARD);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_FORWARD);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftForwardStop() {// 正常向前后到最小角度
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_FORWARD);
        setCDMDriver(80, 0, 1);// 当前实时角度80，硬按键未按下，靠背正在向前调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);// 停止向前打开
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftForwardCannotMove() {// 已经无法再向前，再设置向前
        setSeatBackrestAngle2MoveAvail();
        setCDMDriver(80, 0, 0);// 当前实时角度80，硬按键未按下，靠背无移动
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_FORWARD);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftBackward() {// 正常向后中
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_BACKWARD);
        setCDMDriver(120, 0, 2);// 当前实时角度120，硬按键未按下，靠背正在向后调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_BACKWARD);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_BACKWARD);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftBackwardStop() {// 正常向前后到最大角度停止
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_BACKWARD);
        setCDMDriver(150, 0, 2);// 当前实时角度80，硬按键未按下，靠背正在向后调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);// 停止向后
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftBackwardCannotMove() {// 已经无法再向后，再设置向后
        setSeatBackrestAngle2MoveAvail();
        setCDMDriver(150, 0, 0);// 当前实时角度150，硬按键未按下，靠背无操作
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_BACKWARD);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftOff() {
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
        setCDMDriver(100, 0, 0);// 当前实时角度100，硬按键未按下，设置靠背停止移动
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2LeftParamInvalid() {
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);

        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, PARAM_INVALID);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Left, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Left, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_LEFT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightForward() {// 正常向前中
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_FORWARD);
        setCDMPass(100, 0, 1);// 当前实时角度100，硬按键未按下，靠背正在向前调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_FORWARD);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_FORWARD);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightForwardStop() {// 正常向前后到最大停止
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_FORWARD);
        setCDMPass(80, 0, 1);// 当前实时角度80，硬按键未按下，靠背正在向前调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);// 停止向前
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightForwardCannotMove() {// 已经无法再向前，再设置向前
        setSeatBackrestAngle2MoveAvail();
        setCDMPass(80, 0, 0);// 当前实时角度80，硬按键未按下，靠背无移动
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_FORWARD);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightBackward() {// 正常向后中
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_BACKWARD);
        setCDMPass(120, 0, 2);// 当前实时角度120，硬按键未按下，靠背正在向后调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_BACKWARD);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_BACKWARD);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightBackwardStop() {// 正常向后到最大停止
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_BACKWARD);
        setCDMPass(150, 0, 2);// 当前实时角度150，硬按键未按下，靠背正在向后调整
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);// 停止向前
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightBackwardCannotMove() {// 已经无法再向后，再设置向后
        setSeatBackrestAngle2MoveAvail();
        setCDMPass(150, 0, 2);// 当前实时角度150，硬按键未按下，靠背正在向后调整
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_BACKWARD);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightOff() {
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
        setCDMPass(100, 0, 0);// 当前实时角度100，硬按键未按下，靠背无移动
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
    }

    @Test
    public void testSeatBackrestAngle2MoveRow2RightParamInvalid() {
        setSeatBackrestAngle2MoveAvail();
        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);

        setSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, PARAM_INVALID);
        lockRow2Left();
        Assert.assertEquals(halValueRow2Right, BACKREST_ANGLE_OFF);
        Assert.assertEquals(halStatusRow2Right, 0);
        testSeatBackrestAngle2MoveValue(VehicleAreaSeat.SEAT_ROW_2_RIGHT, BACKREST_ANGLE_OFF);
    }

    public void setSeatBackrestAngle2MoveValue(int areaId, int value) {
        mCarPropertyMgr.setIntProperty(SEAT_BACKREST_ANGLE_2_MOVE, areaId, value);
    }

    public void testSeatBackrestAngle2MoveValue(int areaId, int value) {
        int halValue = mCarPropertyMgr.getIntProperty(SEAT_BACKREST_ANGLE_2_MOVE, areaId);
        Assert.assertEquals(halValue, value);
    }

    public void testSeatBackrestAngle2MoveIsAvailLeft() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_BACKREST_ANGLE_2_MOVE, VehicleAreaSeat.SEAT_ROW_2_LEFT);
        Assert.assertTrue(isAvail);
    }

    public void testSeatBackrestAngle2MoveIsAvailRight() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_BACKREST_ANGLE_2_MOVE, VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        Assert.assertTrue(isAvail);
    }

    public void testSeatBackrestAngle2MoveNotAvailLeft() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_BACKREST_ANGLE_2_MOVE, VehicleAreaSeat.SEAT_ROW_2_LEFT);
        Assert.assertFalse(isAvail);
    }

    public void testSeatBackrestAngle2MoveNotAvailRight() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(SEAT_BACKREST_ANGLE_2_MOVE, VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        Assert.assertFalse(isAvail);
    }

    public void lockRow2Left() {
        try {
            synchronized (lockRow2Left) {
                lockRow2Left.wait(1000);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void lockRow2Right() {
        try {
            synchronized (lockRow2Right) {
                lockRow2Right.wait(1000);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                Log.d(TAG, carPropertyValue.toString());

                int areaId = carPropertyValue.getAreaId();
                if (areaId == VehicleAreaSeat.SEAT_ROW_2_LEFT) {
                    halValueRow2Left = (int) carPropertyValue.getValue();
                    halStatusRow2Left = carPropertyValue.getStatus();
                    synchronized (lockRow2Left) {
                        lockRow2Left.notify();
                    }
                } else if (areaId == VehicleAreaSeat.SEAT_ROW_2_RIGHT) {
                    halValueRow2Right = (int) carPropertyValue.getValue();
                    halStatusRow2Right = carPropertyValue.getStatus();
                    synchronized (lockRow2Right) {
                        lockRow2Right.notify();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };

    private static void setConfig() {
        int cemSvcId = 37;
        int[] cemOperIds = {999};
        int ccSvcId = 135;
        int[] ccOperIds = {200};

        int cdmSvcId = 36;
        int[] cdmOperIds = {999};

        int vddmSvcId = 48;
        int[] vddmOperIds = {999};

        boolean retCem = ipcpClient.setConfig(cemSvcId, cemOperIds);
        Assert.assertTrue(retCem);

        boolean retCc = ipcpClient.setConfig(ccSvcId, ccOperIds);
        Assert.assertTrue(retCc);

        boolean retCdm = ipcpClient.setConfig(cdmSvcId, cdmOperIds);
        Assert.assertTrue(retCdm);


        boolean retVddm = ipcpClient.setConfig(vddmSvcId, vddmOperIds);
        Assert.assertTrue(retVddm);

    }

    public void setSeatBackrestAngle2MoveNotAvail() {
        setCarConfig(1);
        setCEM(VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_ABANDON);
    }

    public void setSeatBackrestAngle2MoveAvail() {
        setCarConfig(3);
        setCDM(100, 0, 0, 100, 0, 0);
        setCEM(VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_DRIVING);
    }

    public void setCEM(int carMode, int usgMode) {
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {carMode, usgMode};
        boolean cemResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        Assert.assertTrue(cemResult);
        delay();
    }

    public void setCarConfig(int cc474) {
        int ccSvcId = 135;
        int ccOperId = 200;
        int[] configs = {474};
        int[] values = {cc474};
        boolean ccResult = ipcpClient.setCarconfigSignal(ccSvcId, ccOperId, configs, values);
        Assert.assertTrue(ccResult);
        delay();
    }

    public void setCDMDriver(int rowSecLeInclPosAngle, int rowSecLeBtnPsd, int seatRowSecLeSwtStsPassSeatSwtInclSts) {
        setCDM(rowSecLeInclPosAngle, rowSecLeBtnPsd, seatRowSecLeSwtStsPassSeatSwtInclSts, 0, 0, 0);
    }

    public void setCDMPass(int rowSecRiInclPosAngle, int rowSecRiBtnPsd, int seatRowSecRiSwtStsPassSeatSwtInclSts) {
        setCDM(0, 0, 0, rowSecRiInclPosAngle, rowSecRiBtnPsd, seatRowSecRiSwtStsPassSeatSwtInclSts);
    }

    public void setCDM(int rowSecLeInclPosAngle, int rowSecLeBtnPsd, int seatRowSecLeSwtStsPassSeatSwtInclSts, int rowSecRiInclPosAngle, int rowSecRiBtnPsd, int seatRowSecRiSwtStsPassSeatSwtInclSts) {
        int cdmSvcId = 36;
        int cdmOperId = 999;
        String[] cdms = {"rowSecLeInclPosAngle", "rowSecLeBtnPsd", "seatRowSecLeSwtStsPassSeatSwtInclSts", "rowSecRiInclPosAngle", "rowSecRiBtnPsd", "seatRowSecRiSwtStsPassSeatSwtInclSts"};
        int[] cdmValues = {rowSecLeInclPosAngle, rowSecLeBtnPsd, seatRowSecLeSwtStsPassSeatSwtInclSts, rowSecRiInclPosAngle, rowSecRiBtnPsd, seatRowSecRiSwtStsPassSeatSwtInclSts};
        boolean cdmResult = ipcpClient.setCDMSignal(cdmSvcId, cdmOperId, cdms, cdmValues);
        Assert.assertTrue(cdmResult);
        delay();
    }

}
